package com.fishy.chat;

import com.fishy.chat.initializer.HttpAndWebSocketChannelInitializer;
import com.fishy.config.ChatConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;


@Component
@Slf4j
public class ChatServer {
    private final ChatConfig chatConfig;
    private final HttpAndWebSocketChannelInitializer httpAndWebSocketChannelInitializer;

    private NioEventLoopGroup bossGroup;
    private NioEventLoopGroup workerGroup;
    private Channel serverChannel;

    public ChatServer(ChatConfig chatConfig, HttpAndWebSocketChannelInitializer httpAndWebSocketChannelInitializer) {
        this.chatConfig = chatConfig;
        this.httpAndWebSocketChannelInitializer = httpAndWebSocketChannelInitializer;
    }

    @Async
    public void start() {
        if (!chatConfig.isEnable()) {
            log.info("Chat server is not enabled.");
            return;
        }

        bossGroup = new NioEventLoopGroup(1);
        workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap chatHttpAndWebsocketServer = new ServerBootstrap();
            chatHttpAndWebsocketServer
                    .group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(httpAndWebSocketChannelInitializer)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            // 绑定端口并启动服务器
            ChannelFuture channelFuture = chatHttpAndWebsocketServer.bind(chatConfig.getPort()).sync();
            serverChannel = channelFuture.channel();

            // 添加监听器来确认服务器是否成功启动
            channelFuture.addListener((ChannelFutureListener) future -> {
                if (future.isSuccess()) {
                    log.info("Chat Server Started Successfully on port {}!", chatConfig.getPort());
                } else {
                    log.error("Chat Server Start Failed!", future.cause());
                }
            });

        } catch (Exception e) {
            log.error("Chat Server Start Failed!", e);
            stop();
        }
    }

    @PreDestroy
    public void stop() {
        log.info("Shutting down Chat Server...");

        if (serverChannel != null) {
            serverChannel.close().syncUninterruptibly();
        }

        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }

        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }

        log.info("Chat Server stopped.");
    }
}